import wx

#模拟标的数据库（代码，名称）
SYMBOL_DB = {
    "510300.SH": "沪深300ETF",
    "510500.SH": "中证500ETF",
    "510050.SH": "上证50ETF",
    "510330.SH": "沪深300ETF易方达",
    "159919.SZ": "沪深300ETF嘉实",
    "159915.SZ": "创业板ETF",
}
class MultiSelectComboBox(wx.Panel):
    def __init__(self, parent, symbol_db=None, **kwargs):
        super().__init__(parent, **kwargs)
        self.symbol_db = symbol_db or SYMBOL_DB  # 使用全局SYMBOL_DB
        self.selected = set()

        # 主布局
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)

        # 输入控件
        self.text_ctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
        self.main_sizer.Add(self.text_ctrl, 1, wx.EXPAND)

        # 弹出窗口
        self.popup = wx.Frame(None, style=wx.FRAME_NO_TASKBAR | wx.BORDER_SIMPLE)
        self.popup.Hide()
        self.list_panel = wx.ScrolledWindow(self.popup)
        self.list_box = wx.CheckListBox(self.list_panel)

        # 弹出窗口布局
        self.popup_sizer = wx.BoxSizer(wx.VERTICAL)
        self.popup_sizer.Add(self.list_box, 1, wx.EXPAND)
        self.list_panel.SetSizer(self.popup_sizer)
        self.list_panel.SetScrollRate(0, 10)

        # 事件绑定
        self.text_ctrl.Bind(wx.EVT_TEXT, self.on_text)
        self.text_ctrl.Bind(wx.EVT_TEXT_ENTER, self.toggle_popup)
        self.text_ctrl.Bind(wx.EVT_LEFT_DOWN, self.toggle_popup)
        self.list_box.Bind(wx.EVT_CHECKLISTBOX, self.on_check)
        self.popup.Bind(wx.EVT_KILL_FOCUS, self.on_popup_lose_focus)

        # 初始化
        self.update_list()
        self.update_display()
        self.SetSizer(self.main_sizer)

    # ---------- 核心功能方法 ----------
    def get_selected_symbols(self):
        """获取选中代码列表"""
        return list(self.selected)

    def set_selected_symbols(self, symbols):
        """设置选中代码"""
        self.selected = set(symbols)
        self.update_display()
        self.update_list()

    def update_display(self):
        """更新文本框显示"""
        display = []
        for code in self.selected:
            name = self.symbol_db.get(code, code)
            display.append(f"{name}({code})")
        self.text_ctrl.SetValue(", ".join(display))

    def update_list(self, filter_str=""):
        """更新选项列表"""
        filtered = []
        for code, name in self.symbol_db.items():
            if filter_str.upper() in code or filter_str.upper() in name.upper():
                filtered.append((code, name))

        # 按代码排序
        filtered.sort(key=lambda x: x[0])

        items = [f"{name}({code})" for code, name in filtered]
        self.list_box.Set(items)

        # 同步选中状态
        for idx, (code, _) in enumerate(filtered):
            self.list_box.Check(idx, code in self.selected)

    # ---------- 事件处理 ----------
    def on_text(self, event):
        """文本输入事件"""
        current = self.text_ctrl.GetValue()

        # 如果是通过选择产生的文本，不处理
        if any(f"({code})" in current for code in self.selected):
            return

        # 处理手动输入
        if "," in current:
            new_symbols = [s.split("(")[-1].strip(")") for s in current.split(",")]
            valid_symbols = [code for code in new_symbols if code in self.symbol_db]
            self.selected = set(valid_symbols)
            self.update_display()
        else:
            self.update_list(current.strip())

    def toggle_popup(self, event):
        """切换弹出窗口"""
        if not self.popup.IsShown():
            self.show_popup()
        else:
            self.hide_popup()

    def on_check(self, event):
        """勾选事件"""
        idx = event.GetInt()
        item = self.list_box.GetString(idx)
        code = item.split("(")[-1].strip(")")

        if self.list_box.IsChecked(idx):
            self.selected.add(code)
        else:
            self.selected.discard(code)

        self.update_display()
        self.text_ctrl.SetFocus()

    def on_popup_lose_focus(self, event):
        """失去焦点时关闭弹窗"""
        self.hide_popup()
        event.Skip()

    # ---------- 窗口控制 ----------
    def show_popup(self):
        """显示弹出窗口"""
        if not self.popup.IsShown():
            # 计算位置
            text_rect = self.text_ctrl.GetScreenRect()
            screen_size = wx.DisplaySize()

            # 计算最佳高度
            max_height = screen_size[1] - text_rect.GetBottom() - 20
            popup_height = min(300, max_height)

            # 设置位置和尺寸
            self.popup.SetPosition((text_rect.x, text_rect.GetBottom() + 2))
            self.popup.SetSize((text_rect.width, popup_height))

            # 更新列表布局
            self.list_panel.Layout()
            self.popup.Show()

    def hide_popup(self):
        """隐藏弹出窗口"""
        if self.popup.IsShown():
            self.popup.Hide()

    # ---------- 样式优化 ----------
    def SetBackgroundColour(self, colour):
        """统一设置背景色"""
        super().SetBackgroundColour(colour)
        self.text_ctrl.SetBackgroundColour(colour)

    def Enable(self, enable=True):
        """禁用/启用控件"""
        super().Enable(enable)
        self.text_ctrl.Enable(enable)
        self.text_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(
                wx.SYS_COLOUR_WINDOW if enable else wx.SYS_COLOUR_BTNFACE
            )
        )
        self.Refresh()